package com.xz.diagnosisOrder.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xz.common.annotation.DataScope;
import com.xz.common.core.domain.entity.SysDept;
import com.xz.common.core.domain.entity.SysUser;
import com.xz.common.exception.ServiceException;
import com.xz.common.utils.DateUtils;
import com.xz.common.utils.SecurityUtils;
import com.xz.common.utils.StringUtils;
import com.xz.diagnosisOrder.domain.*;
import com.xz.diagnosisOrder.dto.DiagnosisTreatmentOrderSaveDto;
import com.xz.diagnosisOrder.enums.PaymentStatusEnum;
import com.xz.diagnosisOrder.mapper.DiagnosisTreatmentOrderDetailMapper;
import com.xz.diagnosisOrder.mapper.DiagnosisTreatmentOrderMapper;
import com.xz.diagnosisOrder.service.*;
import com.xz.diagnosisOrder.vo.DiagnosisTreatmentOrderConsumablesVo;
import com.xz.diagnosisOrder.vo.DiagnosisTreatmentOrderDetailVo;
import com.xz.diagnosisOrder.vo.DiagnosisTreatmentOrderItemVo;
import com.xz.diagnosisOrder.vo.DiagnosisTreatmentOrderVo;
import com.xz.member.domain.MemberInfo;
import com.xz.member.service.IWalletRecordService;
import com.xz.patient.domain.PatientInfo;
import com.xz.patient.mapper.PatientInfoMapper;
import com.xz.system.service.ISysDeptService;
import com.xz.system.service.ISysUserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 就诊单Service业务层处理
 *
 * @author xz
 * @date 2024-03-25
 */
@Service
public class DiagnosisTreatmentOrderServiceImpl extends ServiceImpl<DiagnosisTreatmentOrderMapper, DiagnosisTreatmentOrder> implements IDiagnosisTreatmentOrderService {
  @Autowired
  private DiagnosisTreatmentOrderMapper diagnosisTreatmentOrderMapper;
  @Autowired
  private IDiagnosisTreatmentOrderInitService diagnosisTreatmentOrderInitService;
  @Autowired
  private DiagnosisTreatmentOrderDetailMapper diagnosisTreatmentOrderDetailMapper;
  @Autowired
  private IDiagnosisExpenseService diagnosisExpenseService;
  @Autowired
  private IDiagnosisOrderLogService diagnosisOrderLogService;
  @Autowired
  private IDiagnosisRefundOrderService diagnosisRefundOrderService;
  @Autowired
  private IDiagnosisTreatmentOrderConsumablesService diagnosisTreatmentOrderConsumablesService;
  @Autowired
  private PatientInfoMapper patientInfoMapper;
  @Autowired
  private ISysUserService sysUserService;
  @Autowired
  private ISysDeptService sysDeptService;
  @Autowired
  private IWalletRecordService walletRecordService;

  /**
   * 查询就诊单
   *
   * @param id 就诊单主键
   * @return 就诊单
   */
  @Override
  public DiagnosisTreatmentOrderDetailVo selectDiagnosisTreatmentOrderById(Long id) {
    DiagnosisTreatmentOrder entity = diagnosisTreatmentOrderMapper.selectDiagnosisTreatmentOrderById(id);
    DiagnosisTreatmentOrderDetailVo vo = new DiagnosisTreatmentOrderDetailVo();
    if (null == entity) {
      return vo;
    }
    BeanUtils.copyProperties(entity, vo);
    //设置患者信息
    setPatientInfo(entity, vo);
    //设置药品
    vo.setConsumables(diagnosisTreatmentOrderConsumablesService.getDiagnosisTreatmentOrderConsumablesVo(id));
    //设置套餐/项目
    vo.setDetails(getSubOrderDetailInfos(entity.getOrderNo()));
    return vo;
  }

  /**
   * 查询就诊单
   *
   * @param orderNo 就诊单主键
   * @return 就诊单
   */
  @Override
  public DiagnosisTreatmentOrderDetailVo selectDiagnosisTreatmentOrderByNo(String orderNo) {
    LambdaQueryWrapper<DiagnosisTreatmentOrder> wrapper = Wrappers.lambdaQuery(DiagnosisTreatmentOrder.class);
    wrapper.eq(DiagnosisTreatmentOrder::getOrderNo, orderNo);
    wrapper.eq(DiagnosisTreatmentOrder::getOrderType, 0);

    List<DiagnosisTreatmentOrder> list = list(wrapper);
    DiagnosisTreatmentOrderDetailVo vo = new DiagnosisTreatmentOrderDetailVo();
    if (CollectionUtils.isEmpty(list)) {
      return vo;
    }
    DiagnosisTreatmentOrder entity = list.get(0);
    BeanUtils.copyProperties(entity, vo);
    //设置患者信息
    setPatientInfo(entity, vo);
    //设置药品
    vo.setConsumables(diagnosisTreatmentOrderConsumablesService.getDiagnosisTreatmentOrderConsumablesVo(entity.getId()));
    //设置套餐/项目
    vo.setDetails(getSubOrderDetailInfos(entity.getOrderNo()));
    return vo;
  }
  
  /**
   * 设置患者信息
   * @param entity
   * @param vo
   */
  private void setPatientInfo(DiagnosisTreatmentOrder entity, DiagnosisTreatmentOrderDetailVo vo) {
    // 患者信息
    PatientInfo patientInfo = patientInfoMapper.selectById(entity.getPatientId());
    if (null != patientInfo) {
      vo.setPatientName(patientInfo.getPatientName());
      vo.setPhoneNumber(patientInfo.getPhoneNumber());
      vo.setFileNo(patientInfo.getFileNo());
      vo.setSex(patientInfo.getSex());
      vo.setBirthday(patientInfo.getBirthday());
      Date birthday = patientInfo.getBirthday();
      if (null != birthday) {
        Calendar cal = Calendar.getInstance();
        int currentYear = cal.get(Calendar.YEAR);
        cal.setTime(birthday);
        int birthdayYear = cal.get(Calendar.YEAR);
        vo.setAge(currentYear - birthdayYear);
      }
    }
    //制单人
    if (null != entity.getCreateBy()) {
      SysUser user = sysUserService.selectUserById(entity.getCreateBy());
      if (null != user) {
        vo.setCreateByName(user.getUserName());
      }
    }
    //门店
    if (null != entity.getDeptId()) {
      SysDept dept = sysDeptService.selectDeptById(entity.getDeptId());
      if (null != dept) {
        vo.setDeptName(dept.getDeptName());
      }
    }
  }

  /**
   * 获取套餐/项目数据
   * @param orderNo
   * @return
   */
  private List<DiagnosisTreatmentOrderItemVo> getSubOrderDetailInfos(String orderNo) {
    // 查找该订单下的子订单数据(即套餐与项目数据)
    LambdaQueryWrapper<DiagnosisTreatmentOrder> wrapper = Wrappers.lambdaQuery(DiagnosisTreatmentOrder.class);
    wrapper.eq(DiagnosisTreatmentOrder::getOrderNo, orderNo);
    wrapper.in(DiagnosisTreatmentOrder::getOrderType, 1,2);
    List<DiagnosisTreatmentOrder> list = list(wrapper);
    if (CollectionUtils.isEmpty(list)) {
      return null;
    }
    //将查询的数据转成结果vo类,后续返回
    List<DiagnosisTreatmentOrderItemVo> itemVos = list.stream().map(a->new DiagnosisTreatmentOrderItemVo(a)).collect(Collectors.toList());
    // 查出当时存储的套餐/项目数据，然后从中取出套餐中的项目，赋值到结果中
    List<DiagnosisTreatmentOrderDetail> details = diagnosisTreatmentOrderDetailMapper.selectByOrderNo(orderNo);
    if(!CollectionUtils.isEmpty(details)){
      //按订单id分组
      Map<Long,List<DiagnosisTreatmentOrderDetail>> detailGroup = details.stream().collect(Collectors.groupingBy(DiagnosisTreatmentOrderDetail::getTreatmentOrderId));
      itemVos.forEach(data->{
        //把当时的项目放入套餐里面
        if(data.getType().intValue() == 1){
          List<DiagnosisTreatmentOrderDetail> detailTemp = detailGroup.get(data.getRid());
          data.setItems(detailTemp.stream().map(a->new DiagnosisTreatmentOrderItemVo(a)).collect(Collectors.toList()));
        }
      });
    }
    return itemVos;
  }


  /**
   * 查询就诊单
   *
   * @param id 就诊单主键
   * @return 就诊单
   */
  @Override
  public List<DiagnosisTreatmentOrder> selectById(Long[] id) {
    LambdaQueryWrapper<DiagnosisTreatmentOrder> wrapper = Wrappers.lambdaQuery(DiagnosisTreatmentOrder.class);
    wrapper.in(DiagnosisTreatmentOrder::getId, id);
    return diagnosisTreatmentOrderMapper.selectList(wrapper);
  }

  /**
   * 查询就诊单列表
   *
   * @param diagnosisTreatmentOrder 就诊单
   * @return 就诊单
   */
  @Override
  @DataScope(deptAlias = "d", userAlias = "u")
  public List<DiagnosisTreatmentOrderVo> selectDiagnosisTreatmentOrderVoList(DiagnosisTreatmentOrder diagnosisTreatmentOrder) {
    return diagnosisTreatmentOrderMapper.selectDiagnosisTreatmentOrderVoList(diagnosisTreatmentOrder);
  }

  /**
   * 新增就诊单
   *
   * @param dto 就诊单
   * @return 结果
   */
  @Override
  @Transactional(rollbackFor = Exception.class)
  public int insertDiagnosisTreatmentOrder(DiagnosisTreatmentOrderSaveDto dto) {

    // 初始化主订单
    DiagnosisTreatmentOrder mainOrder = diagnosisTreatmentOrderInitService.initMainOrder(dto);
    // 开始根据项目/套餐，分别创建多个“开单”数据放入集合中，并且计算所有子订单的购买数量，金额放入主订单中
    List<DiagnosisTreatmentOrder> subOrders = diagnosisTreatmentOrderInitService.initSubOrder(mainOrder, dto.getDetails());
    // 计算主,子订单的费用
    diagnosisTreatmentOrderInitService.calculateCosts(mainOrder, subOrders);
    //开始存储主订单
    int flag = diagnosisTreatmentOrderMapper.insertDiagnosisTreatmentOrder(mainOrder);
    if (flag > 0) {
      //开始扣除费用
      diagnosisExpenseService.deductionOfAccountBalance(mainOrder);
      // 开始保存子订单
      saveSubOrder(subOrders);
      // 保存消费药品
      diagnosisTreatmentOrderConsumablesService.saveForOrder(mainOrder, dto);
    }
    return flag;
  }

  /**
   * 开始保存子订单
   *
   * @param subOrders
   */
  private void saveSubOrder(List<DiagnosisTreatmentOrder> subOrders) {
    subOrders.forEach(subOrder -> {
      diagnosisTreatmentOrderMapper.insertDiagnosisTreatmentOrder(subOrder);
      StringBuilder builder = new StringBuilder();
      subOrder.getDetails().forEach(detail -> {
        builder.append("," + detail.getItemName());
        detail.setTreatmentOrderId(subOrder.getId());
        diagnosisTreatmentOrderDetailMapper.insert(detail);
      });
      // 诊疗模块的报表日志
      subOrder.setItemNames(builder.substring(1));
      diagnosisOrderLogService.insertByOrder(subOrder, 3, 2);
    });
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public int refundFeeById(Long[] ids) {

    List<DiagnosisTreatmentOrder> orderList = baseMapper.selectBatchIds(Arrays.asList(ids));
    // 查出数据后开始校验状态是否支持取消,只有到店,并且付款的数据，才能退单
    if (CollectionUtils.isEmpty(orderList)) {
      throw new ServiceException("操作失败，就诊记录不存在");
    }
    // 校验状态
    orderList.forEach(order -> {
      if (null == order || !PaymentStatusEnum.PAID.eq(order.getPaymentStatus())) {
        throw new ServiceException("操作失败，只有已付款状态的单据才能执行退费操作");
      }
    });

    // 更新就诊单数据
    LambdaUpdateWrapper<DiagnosisTreatmentOrder> wrapper = Wrappers.lambdaUpdate(DiagnosisTreatmentOrder.class);
    wrapper.set(DiagnosisTreatmentOrder::getPaymentStatus, PaymentStatusEnum.PENDING_REFUND.getStatus());
    wrapper.set(DiagnosisTreatmentOrder::getUpdateBy, SecurityUtils.getLoginUser().getUserId());
    wrapper.set(DiagnosisTreatmentOrder::getUpdateTime, DateUtils.getNowDate());
    wrapper.in(DiagnosisTreatmentOrder::getId, ids);
    update(wrapper);

    orderList.forEach(order -> {
      LambdaQueryWrapper<DiagnosisTreatmentOrderDetail> queryWrapper = Wrappers.lambdaQuery(DiagnosisTreatmentOrderDetail.class);
      queryWrapper.eq(DiagnosisTreatmentOrderDetail::getTreatmentOrderId, order.getId());
      List<DiagnosisTreatmentOrderDetail> details = diagnosisTreatmentOrderDetailMapper.selectList(queryWrapper);
      if (!CollectionUtils.isEmpty(details)) {
        StringBuilder builder = new StringBuilder();
        details.forEach(data -> {
          builder.append("," + data.getItemName());
        });
        order.setItemNames(builder.substring(1));
      }
    });

    //开始创建退费申请
    diagnosisRefundOrderService.insertByOrder(orderList);
    return 1;
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public boolean setPaymentStatusByBatchId(List<Long> id, Integer status) {

    // 更新挂号单数据
    LambdaUpdateWrapper<DiagnosisTreatmentOrder> wrapper = Wrappers.lambdaUpdate(DiagnosisTreatmentOrder.class);
    wrapper.set(DiagnosisTreatmentOrder::getPaymentStatus, status);
    wrapper.set(DiagnosisTreatmentOrder::getUpdateBy, SecurityUtils.getLoginUser().getUserId());
    wrapper.set(DiagnosisTreatmentOrder::getUpdateTime, DateUtils.getNowDate());
    wrapper.in(DiagnosisTreatmentOrder::getId, id);

    // 只有已退款（退款成功）才会会生成对应的日志报表，钱包记录
    if (status.equals(3)) {
      List<DiagnosisTreatmentOrder> orders = this.baseMapper.selectBatchIds(id);
      orders.forEach(order -> {
        // 诊疗模块的报表日志
        diagnosisOrderLogService.insertByOrder(order, 4, 2);
        // 钱包相关操作
        BigDecimal walletPay = order.getWalletPay();
        if (null != walletPay && walletPay.compareTo(BigDecimal.ZERO) == 1) {
          // 新增钱包流水记录（5-诊疗单退款 , 1:加钱）
          walletRecordService.addBizRecord(order.getMemberCardNo(), 5, 1, order.getOrderNo(), walletPay,
                  order.getDeptId());
          // 返还会员的钱包余额
          diagnosisExpenseService.refundAccountBalance(walletPay, order.getMemberCardNo());
        }
      });
    }
    return update(wrapper);
  }
}
